// https://leetcode.cn/problems/minimum-window-substring/description/
class Solution {
public:
    string minWindow(string s, string t) {
        // 首先定义了两个数组 need 和 window，分别用于记录字符串 t 中每个字符的出现次数以及当前窗口中每个字符的出现次数。
        vector< int> need(58, 0), window(58, 0);//A(65) ~ z(122)范围内的ascii值范围
        for(auto c : t) ++need[c - 'A'];
        // 定义左右指针 left 和 right
        int left = 0, right = 0;
        int count = 0; //记录当前查全的字符个数
        int target = 0; //记录需要查全的字符个数
        // 这个循环遍历字符串 t 中的每个字符，将对应位置的 need 数组的值加一，实际上是统计了 t 中每个字符出现的次数。
        for(auto c : need){
            if(c)   ++target;
        }
        int start = 0; //用于记录符合要求的最小子串的开头
        int len = INT_MAX; //用于记录最小长度
        // 这里使用了 while 循环和双指针来遍历字符串 s。
        while(right < s.size()){
        // 首先获取当前字符的索引值，并将右指针 right 向右移动。
            auto c = s[right] - 'A';
            ++right;
        // 如果当前字符是需要匹配的字符，则将 window 数组中对应位置的值加一，并判断是否已经匹配完该字符，若是则将 count 加一。
            if(need[c] > 0){
                ++window[c];
                if(need[c] == window[c])    ++count;
            }
            // 在内层循环中，判断当前窗口的长度是否比之前记录的最小长度 len 小，若是则更新 start 和 len。然后将左指针 left 右移，缩小窗口的大小，并更新相应的 window 和 count 数组。
            while(count == target){ //所有字符均查全
                if(right - left < len){
                    start = left;
                    len = right  - left;
                }
                auto c = s[left] - 'A';
                ++left;
                if(need[c] > 0){
                    if(need[c] == window[c])
                        --count;
                    --window[c];
                }
            }
        }
        // 在这里，使用了三元运算符来判断最小覆盖子串的长度 len 是否被更新过（初始时 len 被设置为 INT_MAX）。如果 len 没有被更新过，即仍然为 INT_MAX，则返回空字符串 ""；否则，使用 s.substr(start, len) 来提取字符串 s 中从 start 位置开始、长度为 len 的子串作为最终的结果并返回
        return len == INT_MAX ? "" : s.substr(start, len);
    }
};